package com.easipass.unifiedconfig;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import com.easipass.unifiedconfig.core.Authentication;
import com.easipass.unifiedconfig.core.ConfigDomain;
import com.easipass.unifiedconfig.core.IllegalAuthenticationException;
import com.easipass.unifiedconfig.script.ScriptExecuter;
import com.easipass.unifiedconfig.script.parser.ScriptParser;

public class DefaultConfigManager implements ConfigManager{

	protected Map<String, ConfigDomain> repos = new Hashtable<String, ConfigDomain>();
	
	public Parameter getParameter(String domain, String account,
			String module, String parameterName)
	throws NotFoundException, InsufficientPrivillageException {
		if(domain == null) throw new NullPointerException("domain is null");
		
		UCI uci = new UCI(domain, account, module, parameterName);
		return getParameter(uci);
	}

	public Parameter getParameter(UCI uci) throws NotFoundException, InsufficientPrivillageException {
		ConfigDomain repo = repos.get(uci.getDomain());
		if(repo == null) throw new NotFoundException(NotFoundException.Part.DOMAIN, uci);
		Parameter p = repo.getParameter(uci);
		return p;
	}

	public Parameter getParameter(String uciStr) throws NotFoundException, InsufficientPrivillageException {
		return getParameter(new UCI(uciStr));
	}

	public ConfigDomain getConfigDomain(String domain) {
		return repos.get(domain);
	}

	public synchronized boolean registerRepository(ConfigDomain repository, Authentication root)
	throws IllegalAuthenticationException {
		if(repository == null) throw new NullPointerException("repository is null");
		if(!repository.getDomain().equals(root.getDomain())
				|| !root.getUser().equals("root")
				|| !repository.isLegalAuthentication(root))
			throw new IllegalAuthenticationException(root +" is not legal root authentication of the registering ConfigDomain");
		
		if(!repos.containsKey(repository.getDomain())) {
			repos.put(repository.getDomain(), repository);
			return true;
		} else
			return false;
	}
	
	public synchronized boolean unregisterRepository(String domain, Authentication root)
	throws IllegalAuthenticationException {
		ConfigDomain repository = repos.get(domain);
		if(repository == null) return false;
		
		if(!repository.getDomain().equals(root.getDomain())
				|| !root.getUser().equals("root")
				|| !repository.isLegalAuthentication(root))
			throw new IllegalAuthenticationException(root +" is not legal root authentication of the registering ConfigDomain");
		
		repos.remove(repository.getDomain());
		return true;
	}
/*
	public Authentication authenticate(String domain, String account,
			String password) throws NotFoundException {
		ConfigDomain repo = repos.get(domain);
		if(repo == null) throw new NotFoundException(NotFoundException.Part.DOMAIN, domain);
		return repo.authenticate(account, password);
	}
*/
	public Session newSession() {
		return new DefaultSession(this);
	}

	public ScriptExecuter newScriptExecuter() {
		return newScriptExecuter(newSession());
	}

	public ScriptExecuter newScriptExecuter(Session session) {
		ScriptExecuter se = new ScriptParser(new StringReader(""));
		se.setSession(session);
		return se;
	}

	public List<String> listDomains() {
		Collection<ConfigDomain> rs = repos.values();
		List<String> ls = new ArrayList<String>(rs.size());
		for(ConfigDomain cd : rs)
			ls.add(cd.getDomain());
		return ls;
	}

}
